#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <sys/types.h>
#include <sys/types.h>
#include <sys/time.h>
#include <errno.h>
#include <stdbool.h>
#include <stdint.h>
#include "build_link.h"
#include "config.h"
#include "radar_protocol.h"
#include "platform_protocol.h"
#include "video_protocol.h"
#include "log.h"
#include "platform.h"
#include "event.h"
#include "aibox.h"

#define RADAR_IP_COUNT 2  // 定义允许的 IP 地址数量

server_config_t g_server_config;
sync_manager_t g_sync_manager;

// 客户端处理线程函数
void *in_radar_thread(void *arg)
{
    int client_sock = *(int *)arg;  // 直接获取客户端套接字
    char buffer[RADAR_DATA_SIZE];
    int bytes_read;
    // 持续循环接收客户端数据，直到发生异常
    while (1) {
        bytes_read = recv(client_sock, buffer, sizeof(buffer), 0);
        if (bytes_read > 0) {
            analysis_radar_buffer(buffer, bytes_read, RADAR_INCOMING);
        }
        else if (bytes_read == 0) {
            // 客户端断开连接
            printf("Client disconnected.\n");
            break;
        }
        else if (bytes_read == -1) {
            // 发生错误
            perror("recv");
            break;
        }
    }
    // 出现异常或客户端断开连接后关闭套接字
    close(client_sock);
    *(int *)arg = -1;  // 清空客户端套接字
    printf("Client socket closed.\n");
    return NULL;
}

void *out_radar_thread(void *arg)
{
    int client_sock = *(int *)arg;  // 直接获取客户端套接字
    char buffer[RADAR_DATA_SIZE];
    int bytes_read;
    // 持续循环接收客户端数据，直到发生异常
    while (1) {
        bytes_read = recv(client_sock, buffer, sizeof(buffer), 0);
        if (bytes_read > 0) {
            analysis_radar_buffer(buffer, bytes_read, RADAR_OUTGOING);
        }
        else if (bytes_read == 0) {
            // 客户端断开连接
            printf("Client disconnected.\n");
            break;
        }
        else if (bytes_read == -1) {
            // 发生错误
            perror("recv");
            break;
        }
    }
    // 出现异常或客户端断开连接后关闭套接字
    close(client_sock);
    *(int *)arg = -1;  // 清空客户端套接字
    printf("Client socket closed.\n");
    return NULL;
}

void radar_server_mode(void)
{
    int server_sock, client_sock;
    struct sockaddr_in server_addr, client_addr;
    socklen_t client_addr_len = sizeof(client_addr);
    pthread_t in_client_thread, out_client_thread;
    fd_set readfds;
    int max_sd, activity;

    // 创建 TCP 套接字
    if ((server_sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        perror("Socket creation failed");
        return;
    }

    // 设置服务器地址
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = INADDR_ANY;
    server_addr.sin_port = htons(g_config.radar_server_port);

    int opt = 1;
    setsockopt(server_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

    // 绑定套接字
    if (bind(server_sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
        perror("Bind failed");
        close(server_sock);
        return;
    }

    // 开始监听
    if (listen(server_sock, 3) < 0) {
        perror("Listen failed");
        close(server_sock);
        return;
    }

    printf("Radar server listening on port %d...\n", g_config.radar_server_port);

    while (1) {
        if (g_server_config.in_radar_sock > 0 && g_server_config.out_radar_sock > 0) {
            sleep(1);
            continue;
        }
        FD_ZERO(&readfds);
        FD_SET(server_sock, &readfds);
        max_sd = server_sock;

        // 使用 select 等待套接字的活动
        activity = select(max_sd + 1, &readfds, NULL, NULL, NULL);
        if (activity < 0) {
            perror("Select error");
            continue;
        }

        // 如果服务器套接字有活动，说明有新的客户端连接
        if (FD_ISSET(server_sock, &readfds)) {
            if ((client_sock = accept(server_sock, (struct sockaddr *)&client_addr, &client_addr_len)) < 0) {
                perror("Accept failed");
                continue;
            }

            if (memcmp(&client_addr.sin_addr.s_addr, g_config.in_radar_ip, 4) == 0 && g_server_config.in_radar_sock == -1) {
                printf("连接到来向雷达 %s\n", inet_ntoa(client_addr.sin_addr));
                g_server_config.in_radar_sock = client_sock;
                if (pthread_create(&in_client_thread, NULL, in_radar_thread, &g_server_config.in_radar_sock) != 0) {
                    perror("Thread creation failed");
                    close(client_sock);
                    g_server_config.in_radar_sock = -1;  // 失败时清空套接字
                }
            }
            else if (memcmp(&client_addr.sin_addr.s_addr, g_config.out_radar_ip, 4) == 0 && g_server_config.out_radar_sock == -1) {
                printf("连接到去向雷达 %s\n", inet_ntoa(client_addr.sin_addr));
                g_server_config.out_radar_sock = client_sock;
                if (pthread_create(&out_client_thread, NULL, out_radar_thread, &g_server_config.out_radar_sock) != 0) {
                    perror("Thread creation failed");
                    close(client_sock);
                    g_server_config.out_radar_sock = -1;  // 失败时清空套接字
                }
            }
            else {
                printf("雷达服务器拒绝未知地址 %s\n", inet_ntoa(client_addr.sin_addr));
                close(client_sock);
            }
        }
        sleep(1);
    }

    close(server_sock);
}

// 封装创建并连接 TCP 套接字的函数，成功返回套接字描述符，失败返回 -1
int connect_to_server(const uint8_t *ip, int port)
{
    int sock;
    struct sockaddr_in server_addr;
    char ipStr[16];
    sprintf(ipStr, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);

    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        // perror("Socket creation failed");
        return -1;
    }

    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = inet_addr(ipStr);
    server_addr.sin_port = htons(port);

    if (connect(sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
        // perror("Connection failed");
        close(sock);
        return -1;
    }
    printf("连接到服务器 %s:%d\n", ipStr, port);

    return sock;
}

// 来向雷达处理线程（独立管理自己的连接和重连）
void *in_radar_loop(void *arg)
{
    char buffer[RADAR_DATA_SIZE];
    ssize_t bytes_read;

    while (1) {
        int sock = connect_to_server(g_config.in_radar_ip, g_config.radar_client_port);
        if (sock < 0) {
            // 连接失败 → 等待重连
            sleep(1);
            continue;
        }

        // 设置 3 分钟（180 秒）无数据 recv 超时
        struct timeval tv = {.tv_sec = 180, .tv_usec = 0};
        if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) {
            perror("setsockopt SO_RCVTIMEO");
            // 即使失败，也继续使用默认阻塞 recv
        }

        // 进入读取循环
        while (1) {
            bytes_read = recv(sock, buffer, sizeof(buffer), 0);
            if (bytes_read > 0) {
                // 收到数据，处理并重置超时计时器（recv 本身会重置 SO_RCVTIMEO）
                analysis_radar_buffer(buffer, bytes_read, RADAR_INCOMING);
            }
            else if (bytes_read == 0) {
                // 对端正常关闭
                // printf("in_radar_loop: Connection closed by peer.\n");
                break;
            }
            else {
                // bytes_read < 0
                if (errno == EAGAIN || errno == EWOULDBLOCK) {
                    // 3 分钟内无任何数据到来
                    printf("in_radar_loop: No data for 3 minutes, reconnecting...\n");
                }
                else {
                    // 其他 recv 错误
                    perror("in_radar_loop: recv error");
                }
                break;
            }
        }
        close(sock);
        // 等待 1 秒再重连
        sleep(1);
    }
    return NULL;
}

// 去向雷达处理线程（独立管理自己的连接和重连）
void *out_radar_loop(void *arg)
{
    char buffer[RADAR_DATA_SIZE];
    ssize_t bytes_read;

    while (1) {
        int sock = connect_to_server(g_config.out_radar_ip,
                                     g_config.radar_client_port);
        if (sock < 0) {
            // 连接失败，等 1 秒后重试
            sleep(1);
            continue;
        }

        // 设置 3 分钟无数据接收超时
        struct timeval tv = {.tv_sec = 180, .tv_usec = 0};
        if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO,
                       &tv, sizeof(tv)) < 0) {
            perror("out_radar_loop: setsockopt SO_RCVTIMEO");
            // 不影响主逻辑，继续进行阻塞 recv
        }

        // 阻塞读取循环
        while (1) {
            bytes_read = recv(sock, buffer, sizeof(buffer), 0);
            if (bytes_read > 0) {
                // 收到数据，交给分析函数
                analysis_radar_buffer(buffer, bytes_read, RADAR_OUTGOING);
            }
            else if (bytes_read == 0) {
                // 对端正常关闭
                // printf("out_radar_loop: Connection closed by peer.\n");
                break;
            }
            else {
                // bytes_read < 0
                if (errno == EAGAIN || errno == EWOULDBLOCK) {
                    // 超时 180s 内没收到任何数据
                    printf("out_radar_loop: No data for 3 minutes, reconnecting...\n");
                }
                else {
                    // 其他错误
                    perror("out_radar_loop: recv error");
                }
                break;
            }
        }

        close(sock);
        // printf("去向雷达连接断开。正在重连...\n");
        sleep(1);
    }

    return NULL;
}

// 客户端模式
void radar_client_mode()
{
    pthread_t in_thread, out_thread;

    // 分别创建两个线程管理来向和去向的连接
    if (pthread_create(&in_thread, NULL, in_radar_loop, NULL) != 0) {
        perror("Failed to create in_radar_loop thread");
        exit(EXIT_FAILURE);
    }
    if (pthread_create(&out_thread, NULL, out_radar_loop, NULL) != 0) {
        perror("Failed to create out_radar_loop thread");
        exit(EXIT_FAILURE);
    }

    // 主线程等待子线程退出（理论上不会退出，除非程序终止）
    pthread_join(in_thread, NULL);
    pthread_join(out_thread, NULL);

    return;
}

// 服务器端线程函数
void *radar_server_thread(void *arg)
{
    if (g_config.radar_link_mode == RADAR_CLIENT_MODE) {
        radar_client_mode();
    }
    else {
        radar_server_mode();
    }
    return NULL;
}

pthread_t start_radar_server(void)
{
    g_server_config.in_radar_sock = -1;
    g_server_config.out_radar_sock = -1;
    radar_protocol_init();
    pthread_t server_thread_id;
    // 创建一个线程来运行服务器
    if (pthread_create(&server_thread_id, NULL, radar_server_thread, NULL) != 0) {
        perror("Thread creation failed");
        exit(1);
    }
    return server_thread_id;
}

void *video_server_thread(void *arg)
{
    int server_sock, client_sock;
    struct sockaddr_in server_addr, client_addr;
    socklen_t client_addr_len = sizeof(client_addr);
    fd_set readfds;
    int max_sd, activity;
    char *buffer = (char *)malloc(VIDEO_PROTOCOL_DATA_SIZE);
    if (buffer == NULL) {
        perror("malloc");
        return NULL;
    }

    // 创建 TCP 套接字
    if ((server_sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        perror("Socket creation failed");
        return NULL;
    }

    // 设置服务器地址
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = INADDR_ANY;
    server_addr.sin_port = htons(g_config.video_server_port);

    int yes = 1;
    setsockopt(server_sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
    setsockopt(server_sock, SOL_SOCKET, SO_REUSEPORT, &yes, sizeof(yes));
    // 绑定套接字
    if (bind(server_sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
        perror("Bind failed");
        close(server_sock);
        return NULL;
    }

    // 开始监听
    if (listen(server_sock, 3) < 0) {
        perror("Listen failed");
        close(server_sock);
        return NULL;
    }

    printf("摄像头服务器监听端口 %d...\n", g_config.video_server_port);

    while (1) {
        FD_ZERO(&readfds);
        FD_SET(server_sock, &readfds);
        max_sd = server_sock;

        // 使用 select 等待服务器套接字的活动
        activity = select(max_sd + 1, &readfds, NULL, NULL, NULL);
        if (activity < 0) {
            perror("Select error");
            continue;
        }

        if (FD_ISSET(server_sock, &readfds)) {
            client_sock = accept(server_sock, (struct sockaddr *)&client_addr, &client_addr_len);
            if (client_sock < 0) {
                perror("Accept failed");
                continue;
            }

            memset(buffer, 0, VIDEO_PROTOCOL_DATA_SIZE);
            int ret = recv(client_sock, buffer, VIDEO_PROTOCOL_DATA_SIZE, 0);
            if (ret < 0) {
                close(client_sock);
                continue;
            }
            else if (ret == 0) {
                close(client_sock);
                continue;
            }
            // 检查请求头中是否包含 Expect: 100-continue
            if (strstr(buffer, "Expect: 100-continue")) {
                // 发送 HTTP 100 Continue 响应
                const char *continue_response = "HTTP/1.1 100 Continue\r\n\r\n";
                send(client_sock, continue_response, strlen(continue_response), 0);

                // 获取 Content-Length 并继续读取请求体
                char *content_length_str = strstr(buffer, "Content-Length:");
                uint64_t content_length = 0;
                if (content_length_str != NULL) {
                    sscanf(content_length_str, "Content-Length: %ld", &content_length);
                }

                // 检查 Content-Length 是否超出缓冲区大小
                if (content_length > VIDEO_PROTOCOL_DATA_SIZE) {
                    const char *http_413_response =
                        "HTTP/1.1 413 Payload Too Large\r\n"
                        "Content-Type: text/plain\r\n"
                        "Content-Length: 19\r\n\r\n"
                        "Payload Too Large\n";
                    send(client_sock, http_413_response, strlen(http_413_response), 0);
                    fprintf(stderr, "Error: Content-Length exceeds buffer size.\n");
                    close(client_sock);
                    continue;
                }

                if (content_length > 0) {
                    uint64_t total_bytes_read = 0;
                    memset(buffer, 0, VIDEO_PROTOCOL_DATA_SIZE);
                    while (total_bytes_read < content_length) {
                        uint64_t bytes_to_read = content_length - total_bytes_read;
                        if (bytes_to_read > VIDEO_PROTOCOL_DATA_SIZE - total_bytes_read) {
                            bytes_to_read = VIDEO_PROTOCOL_DATA_SIZE - total_bytes_read;
                        }

                        ret = recv(client_sock, buffer + total_bytes_read, bytes_to_read, 0);
                        if (ret <= 0) {
                            printf("error: read ai date\n");
                            break;
                        }
                        total_bytes_read += ret;
                    }
                    parse_json(buffer);
                }
            }
            else {
                char *body_start = strstr(buffer, "\r\n\r\n");
                if (body_start != NULL) {
                    body_start += 4;
                    parse_json(body_start);
                }
            }
            close(client_sock);
        }
    }
    free(buffer);
    return NULL;
}

pthread_t start_video_server(void)
{
    pthread_t server_thread_id = NULL;
    video_protocol_init();
    // 创建一个线程来运行服务器
    if (g_config.need_fusion == 1) {
        if (pthread_create(&server_thread_id, NULL, video_server_thread, NULL) != 0) {
            perror("Thread creation failed");
            exit(1);
        }
        pthread_detach(server_thread_id);  // 分离线程，避免资源泄漏
    }
    else {
        printf("视频服务器未启动\n");
    }
    return server_thread_id;
}

bool connect_socket(uint16_t client_port, uint8_t *server_ip, uint16_t server_port, int *p_sockfd)
{
    struct sockaddr_in servaddr;
    struct sockaddr_in client_addr;
    bool connected = true;
    int sockfd = -1;
    *p_sockfd = -1;

    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        // perror("error : shanma socket");
        return false;
    }

    // 绑定套接字
    bzero(&client_addr, sizeof(client_addr));
    client_addr.sin_family = AF_INET;
    client_addr.sin_addr.s_addr = INADDR_ANY;
    client_addr.sin_port = htons(client_port);

    int opt = 1;
    setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
    setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt));
    if (bind(sockfd, (struct sockaddr *)&client_addr, sizeof(client_addr)) < 0) {
        // perror("error : bind failed shanma");
        close(sockfd);
        return false;
    }

    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(server_port);
    memcpy(&servaddr.sin_addr.s_addr, server_ip, 4);

    if (connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) {
        // perror("error : connect failed shanma");
        close(sockfd);
        return false;
    }
    *p_sockfd = sockfd;
    return true;
}

bool reconnect_platform(void)
{
    int sockfd;
    struct sockaddr_in servaddr;
    struct sockaddr_in client_addr;
    bool connected = true;

    // printf("Reconnecting to platform...\n");
    if (g_server_config.platform_client_sock != -1) {
        close(g_server_config.platform_client_sock);
        g_server_config.platform_client_sock = -1;
        usleep(10000);
    }
    return connect_socket(14000, g_config.shanma_server_ip, g_config.shanma_server_port, &g_server_config.platform_client_sock);
}

void *platform_client_thread(void *arg)
{
    struct sockaddr_in servaddr;
    char buffer[PLATFORM_PROTOCOL_DATA_SIZE];
    int bytes_read;
    bool connected = true;
    struct sockaddr_in client_addr;

    connected = connect_socket(14000, g_config.shanma_server_ip, g_config.shanma_server_port, &g_server_config.platform_client_sock);
    printf("Connected to platform: %s:%d\n", inet_ntoa(*(struct in_addr *)g_config.shanma_server_ip), g_config.shanma_server_port);
    while (1) {
        if (!connected) {
            // 重新连接
            if (reconnect_platform()) {
                printf("Reconnected to platform.\n");
                connected = true;
            }
        }
        else {  // 接收平台数据，心跳包
            bytes_read = recv(g_server_config.platform_client_sock, buffer, sizeof(buffer), 0);
            if (bytes_read > 0) {
                analysis_platform_buffer(buffer, bytes_read);
            }
            else if (bytes_read == 0) {
                // 服务器断开连接
                printf("Platform disconnected.\n");
                close(g_server_config.platform_client_sock);
                g_server_config.platform_client_sock = -1;
                connected = false;
            }
            else if (bytes_read == -1) {
                // 发生错误
                perror("Platform recv error");
                close(g_server_config.platform_client_sock);
                g_server_config.platform_client_sock = -1;
                connected = false;
            }
        }
        sleep(1);
    }
    return NULL;
}

pthread_t start_platform_client(void)
{
    pthread_t client_thread_id;
    // 创建一个线程来运行客户端
    if (pthread_create(&client_thread_id, NULL, platform_client_thread, NULL) != 0) {
        perror("Thread creation failed");
        exit(1);
    }
    return client_thread_id;
}

void init_sync_manager(void)
{
    g_sync_manager.relay_mutex = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;
    g_sync_manager.pole_relay_mutex = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;
}

void init_communication(void)
{
    pthread_t radar_server_thread_id, video_server_thread_id, platform_client_thread_id,
        aibox_server_thread_id;
    init_sync_manager();
    // 创建雷达服务器线程
    radar_server_thread_id = start_radar_server();
    // 创建视觉服务器线程
    video_server_thread_id = start_video_server();
    // 创建平台客户端线程
    platform_client_thread_id = start_platform_client();
    // 创建AI Box 服务器线程
    // aibox_server_thread_id = start_aibox_server();
}

void close_all_socket(void)
{
    if (g_server_config.platform_client_sock != -1) {
        shutdown(g_server_config.platform_client_sock, SHUT_RDWR);
        close(g_server_config.platform_client_sock);
        printf("Platform socket closed.\n");
    }
}